package com.ecarx.vhaltests.hy11.testcases.Utils;

import android.util.Log;

import com.ecarx.vhaltests.IpcpClient;

import java.util.HashMap;

public class IpcpClientHelper {
    private static final String TAG = "IpcpClientHelper";

    private static class StrExecutorWrapper {

        interface IExecutor {
            boolean send(String[] ks, int[] vs);
        }

        private final HashMap<String, Integer> mRequests = new HashMap<>();
        private final IExecutor mExecutor;

        StrExecutorWrapper(IExecutor executor) {
            Log.d(TAG, "StrExecutorWrapper init>>>>>>>>>>>>>>>");
            this.mExecutor = executor;
        }

        private boolean deal(String[] ks, int[] vs) {
            if (0 == ks.length || 0 == vs.length || ks.length < vs.length) return false;
            for (int i = 0; i < ks.length; i++)
                mRequests.put(ks[i], vs[i]);
            Log.d(TAG, "********************************************");
            Log.d(TAG, "mRequest=" + mRequests + ", size=" + mRequests.size());
            Log.d(TAG, "********************************************");
            return true;
        }


        public boolean send(String[] ks, int[] vs) {
            Log.d(TAG, "send >>>>>>>>>");
            if (null == mExecutor) return false;
            if (!deal(ks, vs)) return false;
            if (mRequests.isEmpty()) return false;
            String[] requests = new String[mRequests.size()];
            int[] values = new int[mRequests.size()];
            int i = 0;
            for (String k : mRequests.keySet()) {
                Integer v = mRequests.get(k);
                if (null != v) {
                    requests[i] = k;
                    values[i] = v;
                }
                ++i;
            }
            Log.d(TAG, "********************************************");
            Log.d(TAG, "mRequest=" + mRequests + ", size=" + mRequests.size());
            for (i = 0; i < requests.length; i++)
                Log.d(TAG, "send: k=[" + requests[i] + "], v=[" + values[i] + "]");
            Log.d(TAG, "********************************************");
            return mExecutor.send(requests, values);
        }
    }

    private static class IntExecutorWrapper {

        interface IExecutor {
            boolean send(int[] ks, int[] vs);
        }

        private final HashMap<Integer, Integer> mRequests = new HashMap<>();
        private final IExecutor mExecutor;

        IntExecutorWrapper(IExecutor executor) {
            Log.d(TAG, "IntExecutorWrapper init>>>>>>>>>>>>>>>");
            this.mExecutor = executor;
        }

        private boolean deal(int[] ks, int[] vs) {
            if (0 == ks.length || ks.length < vs.length) return false;
            for (int i = 0; i < ks.length; i++)
                mRequests.put(ks[i], vs[i]);
            Log.d(TAG, "********************************************");
            Log.d(TAG, "mRequest=" + mRequests + ", size=" + mRequests.size());
            Log.d(TAG, "********************************************");
            return true;
        }


        public boolean send(int[] ks, int[] vs) {
            if (null == mExecutor) return false;
            if (!deal(ks, vs)) return false;
            if (mRequests.isEmpty()) return false;
            int[] requests = new int[mRequests.size()];
            int[] values = new int[mRequests.size()];
            int i = 0;
            for (int k : mRequests.keySet()) {
                Integer v = mRequests.get(k);
                if (null != v) {
                    requests[i] = k;
                    values[i] = v;
                }
                ++i;
            }

            Log.d(TAG, "********************************************");
            Log.d(TAG, "mRequest=" + mRequests + ", size=" + mRequests.size());
            for (i = 0; i < requests.length; i++) {
                Log.d(TAG, "send: k=[" + requests[i] + "], v=[" + values[i] + "]");
            }
            Log.d(TAG, "********************************************");
            return mExecutor.send(requests, values);
        }
    }

    interface CEM {
        int SRV_ID = 37;
        int OPCODE = 999;
    }

    interface CDM {
        int SRV_ID = 36;
        int OPCODE = 999;
    }

    interface VDDM {
        int SRV_ID = 48;
        int OPCODE = 999;
    }

    interface BBM {
        int SRV_ID = 33;
        int OPCODE = 999;
    }

    interface VGM {
        int SRV_ID = 49;
        int OPCODE = 999;
    }

    interface DIM {
        int SRV_ID = 0x0127;
    }

    interface CarConfig {
        int SRV_ID = 135;
        int OPCODE = 200;
    }

    interface CLIMATE {
        int SRV_ID = 112;
        int OPCODE = 200;
    }

    interface CarConfig1000 {
        int SRV_ID = 136;
        int OPCODE = 200;
    }

    interface Timeout {
        int SRV_ID = 99;
        int OPCODE = 200;
    }

    private final IpcpClient mClient = new IpcpClient();

    public IpcpClientHelper() {
    }

    public IpcpClient getClient() {
        return mClient;
    }

    private StrExecutorWrapper mCEMExecutor;

    public boolean initCEM() {
        if (null != mCEMExecutor) return true;
        boolean ret = mClient.setConfig(CEM.SRV_ID, new int[]{CEM.OPCODE});
        if (ret)
            mCEMExecutor = new StrExecutorWrapper((requests, values) -> mClient.setCEMSignal(CEM.SRV_ID, CEM.OPCODE, requests, values));
        return ret;
    }

    public boolean setCEM(String[] requests, int[] values) {
//        return mClient.setCEMSignal(CEM.SRV_ID, CEM.OPCODE, requests, values);
        return initCEM() && mCEMExecutor.send(requests, values);
    }

    private StrExecutorWrapper mCDMExecutor;

    public boolean initCDM() {
        if (null != mCDMExecutor) return true;
        boolean ret = mClient.setConfig(CDM.SRV_ID, new int[]{CDM.OPCODE});
        if (ret)
            mCDMExecutor = new StrExecutorWrapper((requests, values) -> mClient.setCDMSignal(CDM.SRV_ID, CDM.OPCODE, requests, values));
        return ret;
    }

    public boolean setCDM(String[] requests, int[] values) {
//        return mClient.setCDMSignal(CDM.SRV_ID, CDM.OPCODE, requests, values);
        return initCDM() && mCDMExecutor.send(requests, values);
    }

    private StrExecutorWrapper mVGMExecutor;

    public boolean initVGM() {
        if (null != mVGMExecutor) return true;
        boolean ret = mClient.setConfig(VGM.SRV_ID, new int[]{VGM.OPCODE});
        if (ret)
            mVGMExecutor = new StrExecutorWrapper((requests, values) -> mClient.setVGMSignal(VGM.SRV_ID, VGM.SRV_ID, requests, values));
        return ret;
    }

    public boolean setVGM(String[] requests, int[] values) {
        return initVGM() && mVGMExecutor.send(requests, values); //mClient.setVGMSignal(VGM.SRV_ID, VGM.OPCODE, requests, values);
    }

    private StrExecutorWrapper mVDDMExecutor;

    public boolean initVDDM() {
        if (null != mVDDMExecutor) return true;
        boolean ret = mClient.setConfig(VDDM.SRV_ID, new int[]{VDDM.OPCODE});
        if (ret)
            mVDDMExecutor = new StrExecutorWrapper((requests, values) -> mClient.setVDDMSignal(VDDM.SRV_ID, VDDM.OPCODE, requests, values));
        return ret;
    }

    public boolean setVDDM(String[] requests, int[] values) {
        return initVDDM() && mVDDMExecutor.send(requests, values);//mClient.setVDDMSignal(VDDM.SRV_ID, VDDM.OPCODE, requests, values);
    }

    private StrExecutorWrapper mBBMExecutor;

    public boolean initBBM() {
        if (null != mBBMExecutor) return true;
        boolean ret = mClient.setConfig(BBM.SRV_ID, new int[]{BBM.OPCODE});
        if (ret)
            mBBMExecutor = new StrExecutorWrapper((requests, values) -> mClient.setBBMSignal(BBM.SRV_ID, BBM.OPCODE, requests, values));
        return ret;
    }

    public boolean setBBM(String[] requests, int[] values) {
        return initBBM() && mBBMExecutor.send(requests, values);// mClient.setBBMSignal(BBM.SRV_ID, BBM.OPCODE, requests, values);
    }


    public boolean initDIM(int[] operIds) {
        return mClient.setConfig(DIM.SRV_ID, operIds);
    }

    public boolean setDIM(int operId, String[] requests, int[] values) {
        return mClient.setDimHUDSignal(DIM.SRV_ID, operId, requests, values);
    }

    private StrExecutorWrapper mClimateExecutor;

    public boolean initClimate() {
        boolean ret = mClient.setConfig(CLIMATE.SRV_ID, new int[]{CLIMATE.OPCODE});
        if (ret)
            mClimateExecutor = new StrExecutorWrapper((requests, values) -> mClient.setClimaSignal(CLIMATE.SRV_ID, CLIMATE.OPCODE, requests, values));
        return ret;
    }

    public boolean setClimateValues(String[] requests, int[] values) {
        return initClimate() && mClimateExecutor.send(requests, values);// mClient.setClimaSignal(CLIMATE.SRV_ID, CLIMATE.OPCODE, requests, values);
    }

    private StrExecutorWrapper mTimeoutExecutor;

    public boolean initTimeout() {
        boolean ret = mClient.setConfig(Timeout.SRV_ID, new int[]{Timeout.OPCODE});
        if (ret)
            mTimeoutExecutor = new StrExecutorWrapper((requests, values) -> mClient.setTimeoutSignal(Timeout.SRV_ID, Timeout.OPCODE, requests, values));
        return ret;
    }

    public boolean setTimeout(String[] requests, int[] values) {
        return initTimeout() && mTimeoutExecutor.send(requests, values);//mClient.setTimeoutSignal(Timeout.SRV_ID, Timeout.OPCODE, requests, values);
    }

    private IntExecutorWrapper mCCExecutor;

    public boolean initCarConfig() {
        if (null != mCCExecutor) return true;
        boolean ret = mClient.setConfig(CarConfig.SRV_ID, new int[]{CarConfig.OPCODE});
        if (ret)
            mCCExecutor = new IntExecutorWrapper((requests, values) -> mClient.setCarconfigSignal(CarConfig.SRV_ID, CarConfig.OPCODE, requests, values));
        return ret;
    }

    public boolean setCarConfig(int[] requests, int[] values) {
        return initCarConfig() && mCCExecutor.send(requests, values);//mClient.setCarconfigSignal(CarConfig.SRV_ID, CarConfig.OPCODE, requests, values);
    }

    private IntExecutorWrapper mCC1000Executor;

    public boolean initCarConfig1000() {
        if (null != mCC1000Executor) return true;
        boolean ret = mClient.setConfig(CarConfig1000.SRV_ID, new int[]{CarConfig1000.OPCODE});
        if (ret)
            mCC1000Executor = new IntExecutorWrapper((requests, values) -> mClient.setCarconfig1000Signal(CarConfig1000.SRV_ID, CarConfig1000.OPCODE, requests, values));
        return ret;
    }

    public boolean setCarConfig1000(int[] requests, int[] values) {
        return initCarConfig1000() && mCC1000Executor.send(requests, values);
    }

    public boolean setMode(int carmod, int usrmod) {
        return setCEM(new String[]{"vehModMngtGlbSafe1CarModSts1", "vehModMngtGlbSafe1UsgModSts"}, new int[]{carmod, usrmod});
    }

    public boolean setCarMode(int mode) {
        return setCEM(new String[]{"vehModMngtGlbSafe1CarModSts1"}, new int[]{mode});
    }

    public boolean setUsrMode(int mode) {
        return setCEM(new String[]{"vehModMngtGlbSafe1UsgModSts"}, new int[]{mode});
    }

    public static void delay(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void delay() {
        delay(100);
    }
}
